package de.playmee;

import java.util.ArrayList;
import java.util.List;

import de.playmee.geo.Region;
import de.playmee.handler.AccountHandler;
import de.playmee.handler.ChannelHandler;
import de.playmee.handler.ChannelTrackRatingHandler;
import de.playmee.handler.MusicHandler;
import de.playmee.handler.PlaylistHandler;
import de.playmee.handler.RegionHandler;
import de.playmee.services.LoadingService.DownloadTrackDataListener;
import de.playmee.services.LoadingService.UploadTrackDataListener;
import de.playmee.services.MusicService.DataChangeListener;
import de.playmee.tasks.UpdateWeatherConditionsTask.WeatherUpdatedListener;
import android.app.Application;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.TypedValue;

public class Playmee extends Application {

	private AccountHandler aHandler;
	private ChannelHandler cHandler;
	private MusicHandler mHandler;
	private PlaylistHandler pHandler;
	private RegionHandler rHandler;
	private ChannelTrackRatingHandler ctrHandler;
	
	private ImageManager imageManager;

	private List<DownloadTrackDataListener> downloadTrackDataListeners = new ArrayList<DownloadTrackDataListener>();
	private List<UploadTrackDataListener> uploadTrackDataListeners = new ArrayList<UploadTrackDataListener>();
	
	private List<DataChangeListener> dataChangeListeners = new ArrayList<DataChangeListener>();
	
	private List<WeatherUpdatedListener> weatherUpdatedListeners = new ArrayList<WeatherUpdatedListener>();
	private Weather weather = new Weather();
	
	public Region currentRegion;
	public boolean isStartingChannelInRegion = false;
	
	/**
	 * sets the image manager
	 * 
	 * @param imageManager
	 */
	public synchronized void setImageManager(ImageManager imageManager) {
		this.imageManager = imageManager;
	}
	
	/**
	 * @return imageManager
	 */
	public synchronized ImageManager getImageManager() {
		return imageManager;
	}
	
	/**
	 * sets the account handler
	 * 
	 * @param aHandler
	 */
	public synchronized void setAccountHandler(AccountHandler aHandler) {
		this.aHandler = aHandler;
	}

	/**
	 * sets the channel handler
	 * 
	 * @param cHandler
	 */
	public synchronized void setChannelHandler(ChannelHandler cHandler) {
		this.cHandler = cHandler;
	}

	/**
	 * sets the music handler
	 * 
	 * @param mHandler
	 */
	public synchronized void setMusicHandler(MusicHandler mHandler) {
		this.mHandler = mHandler;
	}

	/**
	 * sets the playlist handler
	 * 
	 * @param pHandler
	 */
	public synchronized void setPlaylistHandler(PlaylistHandler pHandler) {
		this.pHandler = pHandler;
	}
	
	/**
	 * sets the region handler
	 * 
	 * @param rHandler
	 */
	public synchronized void setRegionHandler(RegionHandler rHandler) {
		this.rHandler = rHandler;
	}
	
	/**
	 * sets the channel-track-rating handler
	 * 
	 * @param ctrHandler
	 */
	public synchronized void setChannelTrackRatingHandler(ChannelTrackRatingHandler ctrHandler) {
		this.ctrHandler = ctrHandler;
	}
	
	/**
	 * sets the weather
	 * 
	 * @param weather
	 */
	public synchronized void setWeather(Weather weather) {
		this.weather = weather;
	}

	/**
	 * @return aHandler
	 */
	public synchronized AccountHandler getAccountHandler() {
		return aHandler;
	}

	/**
	 * @return cHandler
	 */
	public synchronized ChannelHandler getChannelHandler() {
		return cHandler;
	}

	/**
	 * @return mHandler
	 */
	public synchronized MusicHandler getMusicHandler() {
		return mHandler;
	}

	/**
	 * @return pHandler
	 */
	public synchronized PlaylistHandler getPlaylistHandler() {
		return pHandler;
	}
	
	/**
	 * 
	 * @return rHandler
	 */
	public synchronized RegionHandler getRegionHandler() {
		return rHandler;
	}
	
	/**
	 * @return ctrHandler
	 */
	public synchronized ChannelTrackRatingHandler getChannelTrackRatingHandler() {
		return ctrHandler;
	}
	
	/**
	 * @return weather
	 */
	public synchronized Weather getWeather() {
		return weather;
	}
	
	/**
	 * adds a DownloadTrackDataListener
	 * 
	 * @param downloadTrackDataListener
	 */
	public void addDownloadTrackDataListener(DownloadTrackDataListener downloadTrackDataListener) {
		synchronized(downloadTrackDataListeners) {
			downloadTrackDataListeners.add(downloadTrackDataListener);
		}
	}
	
	/**
	 * removes a DownloadTrackDataListener
	 * 
	 * @param downloadTrackDataListener
	 */
	public void removeDownloadTrackDataListener(DownloadTrackDataListener downloadTrackDataListener) {
		synchronized(downloadTrackDataListeners) {
			downloadTrackDataListeners.remove(downloadTrackDataListener);
		}
	}
	
	/**
	 * @return downloadTrackDataListeners
	 */
	public List<DownloadTrackDataListener> getDownloadTrackDataListeners() {
		return downloadTrackDataListeners;
	}
	
	/**
	 * adds a uploadTrackDataListener
	 * 
	 * @param uploadTrackDataListener
	 */
	public void addUploadTrackDataListener(UploadTrackDataListener uploadTrackDataListener) {
		synchronized(uploadTrackDataListeners) {
			uploadTrackDataListeners.add(uploadTrackDataListener);
		}
	}
	
	/**
	 * removes a uploadTrackDataListener
	 * 
	 * @param uploadTrackDataListener
	 */
	public void removeUploadTrackDataListener(UploadTrackDataListener uploadTrackDataListener) {
		synchronized(uploadTrackDataListeners) {
			uploadTrackDataListeners.remove(uploadTrackDataListener);
		}
	}
	
	/**
	 * @return dataChangeListeners
	 */
	public List<UploadTrackDataListener> getUploadTrackDataListeners() {
		return uploadTrackDataListeners;
	}
	
	/**
	 * adds a dataChangeListener
	 * 
	 * @param dataChangeListener
	 */
	public void addDataChangeListener(DataChangeListener dataChangeListener) {
		synchronized(dataChangeListeners) {
			dataChangeListeners.add(dataChangeListener);
		}
	}
	
	/**
	 * removes a dataChangeListener
	 * 
	 * @param dataChangeListener
	 */
	public void removeDataChangeListener(DataChangeListener dataChangeListener) {
		synchronized(dataChangeListeners) {
			dataChangeListeners.remove(dataChangeListener);
		}
	}
	
	/**
	 * @return uploadTrackDataListeners
	 */
	public List<DataChangeListener> getDataChangeListeners() {
		return dataChangeListeners;
	}
	
	/**
	 * adds a WeatherUpdatedListener
	 * 
	 * @param weatherUpdatedListener
	 */
	public void addWeatherUpdatedListener(WeatherUpdatedListener weatherUpdatedListener) {
		synchronized(weatherUpdatedListeners) {
			weatherUpdatedListeners.add(weatherUpdatedListener);
		}
	}
	
	/**
	 * removes a WeatherUpdatedListener
	 * 
	 * @param weatherUpdatedListener
	 */
	public void removeWeatherUpdatedListener(WeatherUpdatedListener weatherUpdatedListener) {
		synchronized(weatherUpdatedListeners) {
			weatherUpdatedListeners.remove(weatherUpdatedListener);
		}
	}
	
	/**
	 * @return weatherUpdatedListeners
	 */
	public List<WeatherUpdatedListener> getWeatherUpdatedListeners() {
		return weatherUpdatedListeners;
	}
	
	/**
	 * Indicates whether network connectivity exists.
	 * 
	 * @return true if network connectivity exists, false otherwise
	 */
	public synchronized boolean hasNetworkConnection() {
	    boolean hasConnectedWifi = false;
	    boolean hasConnectedMobile = false;

	    ConnectivityManager cm = (ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
	    NetworkInfo[] netInfo = cm.getAllNetworkInfo();
	    for (NetworkInfo ni : netInfo) {
	        if (ni.getTypeName().equalsIgnoreCase("WIFI"))
	            if (ni.isConnected())
	                hasConnectedWifi = true;
	        if (ni.getTypeName().equalsIgnoreCase("MOBILE"))
	            if (ni.isConnected())
	                hasConnectedMobile = true;
	    }
	    return hasConnectedWifi || hasConnectedMobile;
	}
	
	/**
	 * Indicates whether the gps location provider is enabled
	 * 
	 * @return true if the provider is enabled, false otherwise
	 */
	public synchronized boolean gpsLocationProviderIsEnabled() {
		LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
		return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
	}
	
	/**
	 * Indicates whether the network (cell tower or wifi)  location provider is enabled
	 * 
	 * @return true if the provider is enabled, false otherwise
	 */
	public synchronized boolean networkLocationProviderIsEnabled() {
		LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
		return locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
	}
	
	/**
	 * calculate pixels from dp
	 * 
	 * @param dp
	 * @return
	 */
	public int dpToPx(int dp) {
		return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
				getResources().getDisplayMetrics());
	}
}
